Skip to content

[#284] Fix false recovery intents from wallet rejection#286

Merged
realproject7 merged 1 commit intomainfrom
task/284-wallet-rejection-detection
Mar 18, 2026
Merged

[#284] Fix false recovery intents from wallet rejection#286
realproject7 merged 1 commit intomainfrom
task/284-wallet-rejection-detection

Conversation

@realproject7
Copy link
Copy Markdown
Owner

Summary

  • Moved onIntentSave + onTxConfirmed to after writeContractAsync succeeds, not before
  • If the wallet rejects for any reason (any error message, any wallet), no intent is ever written to localStorage
  • Removed isUserRejection() entirely — no more brittle string matching against wallet error messages
  • Net -20 lines: simpler and more correct

Root cause

The old flow saved intent before the wallet popup. If the wallet rejected with a non-standard error message (e.g., Rabby, Frame, hardware wallets), isUserRejection() wouldn't match, leaving a false intent that triggered the recovery banner for a tx that never happened.

Test plan

  • Reject wallet popup with MetaMask — verify no intent in localStorage, no recovery banner on reload
  • Reject wallet popup with Rabby/other wallet — same verification
  • Complete a publish, kill the tab during indexing — verify recovery banner appears on reload
  • npm run typecheck passes

Fixes #284

🤖 Generated with Claude Code

Move intent save to after writeContractAsync succeeds instead of
before. If the wallet rejects (any error message, any wallet), no
intent is ever written to localStorage. Removes brittle
isUserRejection() pattern matching entirely.

Fixes #284

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T2b Review — APPROVED

Elegant fix. Moving onIntentSave + onTxConfirmed to after writeContractAsync succeeds means:

  • Wallet rejection = no intent ever written (no false recovery)
  • isUserRejection() heuristic eliminated entirely (no string-matching fragility)
  • The semantic onIndexed misuse from PR #282 is gone as a side effect

Intent + txHash are saved back-to-back after wallet signs but before receipt polling — if the page crashes between sign and receipt confirmation, recovery still works correctly. Net -20 lines, strictly better.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE

Summary

This change removes the brittle wallet-rejection string matching and fixes the false recovery-intent bug by only writing intent state after writeContractAsync succeeds. The earlier receipt-poll and indexer recovery paths remain intact because the tx hash is still persisted before receipt waiting.

Findings

  • No blocking findings from this review pass.

Decision

Approving from my side. GitHub checks were still pending at the time of review.

@realproject7 realproject7 merged commit 5739c89 into main Mar 18, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] Brittle wallet rejection detection leaves false recovery intents

2 participants